package pig

type pipeline[T any] struct {
	injector  T
	pipelines []func(T, func(T))
}

// 创建一个管道
func newPipeline[T any]() *pipeline[T] {
	return &pipeline[T]{}
}

// 发送数据到管道
func (h *pipeline[T]) Send(i T) *pipeline[T] {
	h.injector = i
	return h
}

// 通过管道
func (h *pipeline[T]) Through(unit func(T, func(T))) *pipeline[T] {
	h.pipelines = append(h.pipelines, unit)
	return h
}

// 执行管道
func (h *pipeline[T]) Then(p func(T)) {
	f := reduceRight(
		h.pipelines,
		func(f func(T), f2 func(T, func(T)), i int) func(T) {
			return func(i T) {
				f2(i, f)
			}
		},
		p,
	)
	f(h.injector)
}

func reduceRight[T any, R any](collection []T, accumulator func(agg R, item T, index int) R, initial R) R {
	for i := len(collection) - 1; i >= 0; i-- {
		initial = accumulator(initial, collection[i], i)
	}
	return initial
}
